home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / suckmods.zip / SUCKMODS.ZIP / suck05 / src / client.qc < prev    next >
Text File  |  1997-05-13  |  57KB  |  2,458 lines

  1. // Prototypes for functions referenced in this file.
  2. void () W_WeaponFrame;
  3. void() W_SetCurrentAmmo;
  4. void() player_pain;
  5. void() player_stand1;
  6. void (vector org) spawn_tfog;
  7. void (vector org, entity death_owner) spawn_tdeath;
  8. string(string old) RandomLevel;
  9. void() printstatus;
  10. void() ghost_daemon_think;
  11. void(entity e) RegenerateAmmo;
  12. void () checkreg;
  13. void(entity e, float chan, string samp, float vol, float atten) playsound;
  14. void () SetRuneInfoMsg;
  15.  
  16. float    modelindex_eyes, modelindex_player;
  17.  
  18. //===========================================================================  
  19. // Player forwarding configuration.  See teamplay.txt to learn how to turn
  20. // this feature on.
  21. //
  22. // Player forwarding must be configured in the PlayerPreThink function
  23. // below, because the quakeC interpreter is broken and your quake server
  24. // will crash otherwise.  This is not my fault - I simply push QuakeC to
  25. // the limit.  The only configuration which you want to do here is
  26. // the number of players, right below.
  27.  
  28. // If your server supports 16 players, set this to 16.  If 8, set it to 8.
  29. // Contact your local elementary school if this is incomprehensible to you.
  30. float   fwd_supported_players = 16;
  31.  
  32. //
  33. //===========================================================================  
  34.  
  35. // -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
  36. // Note to the server admin: 
  37. //    If you are going to use the SuckMods on your server, you are
  38. // required to credit me in the MOTD.  It would also be nice if you'd
  39. // leave my email address in so that I can get bug reports and such.
  40. //        - Suck
  41. void() MOTD =
  42. {
  43.     self.motd_time = time + 1;
  44.     self.motd_count = self.motd_count + 1;
  45.     if (self.motd_count < 5 && self.motd_count > 2)
  46.         centerprint(self, "This server is running Threewave CTF\nplus ╙⌡πδ═∩Σ≤ Version 0.5\n\nThe special mods on this server are by\nSuck, suck@linux.mit.edu.\n\nSuck is your admin.\n");
  47.     else if ((self.motd_count < 9) && (self.team == TEAM_COLOR1 + 1))
  48.         centerprint(self, "You are on the ╥┼─ team.\n\nType impulse 26 for help.\n\nSee http://linux.mit.edu/quake\nfor information about these mods.\n"); // red team
  49.     else if ((self.motd_count < 9) && (self.team == TEAM_COLOR2 + 1))
  50.         centerprint(self, "You are on the ┬╠╒┼ team.\n\nType impulse 26 for help.\n\nSee http://linux.mit.edu/quake\nfor information about these mods.\n"); // blue team
  51.     else if (self.motd_count < 10) {
  52.         sprint(self, "Mail comments/suggestions to suck@linux.mit.edu\n");
  53.         self.motd_time = 0;
  54.         if (teamplay&TEAM_STATUS_BAR)
  55.             self.status_time = time + 1;
  56.         else
  57.             self.status_time = -1;        
  58.  
  59.     }
  60. };
  61.  
  62. // ZOID: with several effects doing the dimlight thing, they just can't
  63. // turn it off.  Do not set self.effects with EF_DIMLIGHT directly.  This
  64. // will automatically do it when CheckPowerups is called
  65. // EF_DIMLIGHT is used;
  66. // 1. Invincible (Pentagram)
  67. // 2. Super Damage (Quad Power)
  68. // 3. Having Flag in Capture
  69. // self is player
  70. void () CheckDimLight = {
  71.     local float flag;
  72.  
  73.     flag = 0;
  74.     // invincible
  75.     if (self.invincible_finished > time)
  76.         flag = 1;
  77.     // quad
  78.     if (self.super_damage_finished > time)
  79.         flag = 1;
  80.     // flag
  81.     if (self.player_flag & ITEM_ENEMY_FLAG)
  82.         flag = 1;
  83.  
  84.     if (flag)
  85.         self.effects = self.effects | EF_DIMLIGHT;
  86.     else
  87.         self.effects = self.effects - (self.effects & EF_DIMLIGHT);
  88. };
  89.  
  90. /*
  91. =============================================================================
  92.  
  93.                 LEVEL CHANGING / INTERMISSION
  94.  
  95. =============================================================================
  96. */
  97.  
  98. float    intermission_running;
  99. float    intermission_exittime;
  100.  
  101. /*QUAKED info_intermission (1 0.5 0.5) (-16 -16 -16) (16 16 16)
  102. This is the camera point for the intermission.
  103. Use mangle instead of angle, so you can set pitch or roll as well as yaw.  'pitch roll yaw'
  104. */
  105. void() info_intermission =
  106. {
  107. };
  108.  
  109.  
  110. void() SetChangeParms =
  111. {
  112.     if (self.health <= 0)
  113.     {
  114.         SetNewParms ();
  115.         return;
  116.     }
  117.  
  118. // remove items
  119.     self.items = self.items - (self.items & 
  120.     (IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD) );
  121.     
  122. // cap super health
  123.     if (self.health > 100)
  124.         self.health = 100;
  125.     if (self.health < 50)
  126.         self.health = 50;
  127.     parm1 = self.items;
  128.     parm2 = self.health;
  129.     parm3 = self.armorvalue;
  130.     if (self.ammo_shells < 25)
  131.         parm4 = 25;
  132.     else
  133.         parm4 = self.ammo_shells;
  134.     parm5 = self.ammo_nails;
  135.     parm6 = self.ammo_rockets;
  136.     parm7 = self.ammo_cells;
  137.     parm8 = self.weapon;
  138.     parm9 = self.armortype * 100;
  139. // *TEAMPLAY*
  140.     parm10 = self.lastteam;    // Save the current team of the player
  141.  
  142. // Save the regcode between level changes.
  143.     parm11 = self.regcode;
  144.  
  145.     parm16 = self.player_flag;
  146. };
  147.  
  148. void() SetNewParms =
  149. {
  150.     parm1 = IT_SHOTGUN | IT_AXE | IT_HOOK;
  151.     parm2 = 100;
  152.     parm3 = 0;
  153.     parm4 = 25;
  154.     parm5 = 0;
  155.     parm6 = 0;
  156.     parm7 = 0;
  157.     parm8 = 1;
  158.     parm9 = 0;
  159. // *TEAMPLAY*
  160.     parm10 = -1;    // Reset
  161.     parm11 = self.regcode;
  162.     parm16 = 0;
  163. };
  164.  
  165. void() DecodeLevelParms =
  166. {
  167.     self.player_flag = self.player_flag | parm16;
  168.     self.player_flag = self.player_flag - (self.player_flag & ITEM_ENEMY_FLAG);
  169.     self.skin = (self.player_flag & 65280)/256;
  170.  
  171.     if (serverflags)
  172.     {
  173.         if (world.model == "maps/start.bsp")
  174.             SetNewParms ();        // take away all stuff on starting new episode
  175.     }
  176.     
  177.     self.items = IT_SHOTGUN | IT_AXE | IT_HOOK | IT_ARMOR1;
  178.     self.health = 100;
  179.     self.armorvalue = 50;
  180.     self.ammo_shells = 25;
  181.     self.ammo_nails = 0;
  182.     self.ammo_rockets = 0;
  183.     self.ammo_cells = 0;
  184.     self.weapon = IT_SHOTGUN;
  185.     self.armortype = 0.3;
  186.  
  187.     // Grab the regcode...
  188.     self.regcode = parm11;
  189.  
  190.     if (!(self.items &(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)))
  191.     {
  192.         self.armortype=0.3;
  193.         self.armorvalue=50;
  194.         self.items=self.items|IT_ARMOR1;
  195.     }
  196. // *TEAMPLAY*
  197.     if(TeamColorIsLegal(parm10 - 1))
  198.         self.lastteam = parm10;
  199. };
  200.  
  201. /*
  202. ============
  203. FindIntermission
  204.  
  205. Returns the entity to view from
  206. ============
  207. */
  208. entity() FindIntermission =
  209. {
  210.     local    entity spot;
  211.     local    float cyc;
  212.  
  213. // look for info_intermission first
  214.     spot = find (world, classname, "info_intermission");
  215.     if (spot)
  216.     {    // pick a random one
  217.         cyc = random() * 4;
  218.         while (cyc > 1)
  219.         {
  220.             spot = find (spot, classname, "info_intermission");
  221.             if (!spot)
  222.                 spot = find (spot, classname, "info_intermission");
  223.             cyc = cyc - 1;
  224.         }
  225.         return spot;
  226.     }
  227.  
  228. // then look for the start position
  229.     spot = find (world, classname, "info_player_start");
  230.     if (spot)
  231.         return spot;
  232.     
  233. // testinfo_player_start is only found in regioned levels
  234.     spot = find (world, classname, "testplayerstart");
  235.     if (spot)
  236.         return spot;
  237.     
  238.     objerror ("FindIntermission: no spot");
  239. };
  240.  
  241.  
  242. string nextmap;
  243. void() GotoNextMap =
  244. {
  245.     if (cvar("samelevel"))    // if samelevel is set, stay on same level
  246.         changelevel (mapname);
  247.     else
  248.         changelevel (nextmap);
  249. };
  250.  
  251.  
  252. void() ExitIntermission =
  253. {
  254. // skip any text in deathmatch
  255.     if (deathmatch)
  256.     {
  257.         GotoNextMap ();
  258.         return;
  259.     }
  260.     
  261.     intermission_exittime = time + 1;
  262.     intermission_running = intermission_running + 1;
  263.  
  264.     GotoNextMap ();
  265. };
  266.  
  267. /*
  268. ============
  269. IntermissionThink
  270.  
  271. When the player presses attack or jump, change to the next level
  272. ============
  273. */
  274. void() IntermissionThink =
  275. {
  276.     if (time < intermission_exittime)
  277.         return;
  278.  
  279.     if (!self.button0 && !self.button1 && !self.button2)
  280.         return;
  281.     
  282.     ExitIntermission ();
  283. };
  284.  
  285. void() execute_changelevel =
  286. {
  287.     local entity    pos;
  288.  
  289.     intermission_running = 1;
  290.     
  291. // enforce a wait time before allowing changelevel
  292.     if (deathmatch)
  293.         intermission_exittime = time + 8;
  294.     else
  295.         intermission_exittime = time + 2;
  296.  
  297.     WriteByte (MSG_ALL, SVC_CDTRACK);
  298.     WriteByte (MSG_ALL, 3);
  299.     WriteByte (MSG_ALL, 3);
  300.     
  301.     pos = FindIntermission ();
  302.  
  303.     other = find (world, classname, "player");
  304.     while (other != world)
  305.     {
  306.         other.view_ofs = '0 0 0';
  307.         other.angles = other.v_angle = pos.mangle;
  308.         other.fixangle = TRUE;        // turn this way immediately
  309.         other.nextthink = time + 0.5;
  310.         other.takedamage = DAMAGE_NO;
  311.         other.solid = SOLID_NOT;
  312.         other.movetype = MOVETYPE_NONE;
  313.         other.modelindex = 0;
  314.         setorigin (other, pos.origin);
  315.         other = find (other, classname, "player");
  316.     }    
  317.  
  318.  
  319.     WriteByte (MSG_ALL, SVC_INTERMISSION);
  320. };
  321.  
  322.  
  323. void() changelevel_touch =
  324. {
  325.     local entity    pos;
  326.  
  327.     if (other.classname != "player")
  328.         return;
  329.  
  330.     if ((cvar("noexit") == 1) && (teamplay & TEAM_CAPTURE_FLAG))
  331.         return;
  332.  
  333.     if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
  334.     {
  335.         T_Damage (other, self, self, 50000);
  336.         return;
  337.     }
  338.  
  339.     if (coop || deathmatch)
  340.     {
  341.         bprint (other.netname);
  342.         bprint (" exited the level\n");
  343.     }
  344.     
  345. // ZOID - go to next level randomly
  346.     if (deathmatch)
  347.         nextmap = RandomLevel(mapname);
  348.     else
  349.         nextmap = self.map;
  350.  
  351.     SUB_UseTargets ();
  352.  
  353.     if ( (self.spawnflags & 1) && (deathmatch == 0) )
  354.     {    // NO_INTERMISSION
  355.         GotoNextMap();
  356.         return;
  357.     }
  358.     
  359.     self.touch = SUB_Null;
  360.  
  361. // we can't move people right now, because touch functions are called
  362. // in the middle of C movement code, so set a think time to do it
  363.     self.think = execute_changelevel;
  364.     self.nextthink = time + 0.1;
  365. };
  366.  
  367. /*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION
  368. When the player touches this, he gets sent to the map listed in the "map" variable.  Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
  369. */
  370. void() trigger_changelevel =
  371. {
  372.     if (!self.map)
  373.         objerror ("chagnelevel trigger doesn't have map");
  374.     
  375.     InitTrigger ();
  376.     self.touch = changelevel_touch;
  377. };
  378.  
  379.  
  380. /*
  381. =============================================================================
  382.  
  383.                 PLAYER GAME EDGE FUNCTIONS
  384.  
  385. =============================================================================
  386. */
  387.  
  388. void() set_suicide_frame;
  389.  
  390. // called by ClientKill and DeadThink
  391. void() respawn =
  392. {
  393.     self.killed=1;
  394.     // SUCK: Keep track of the number of deaths for the status bar.
  395.     self.num_deaths = self.num_deaths + 1;
  396.     if (coop)
  397.     {
  398.         // make a copy of the dead body for appearances sake
  399.         CopyToBodyQue (self);
  400.         // get the spawn parms as they were at level start
  401.         setspawnparms (self);
  402.         parm11=self.regcode;
  403.         // respawn        
  404.         PutClientInServer ();
  405.     }
  406.     else if (deathmatch)
  407.     {
  408.         // make a copy of the dead body for appearances sake
  409.         CopyToBodyQue (self);
  410.         // set default spawn parms
  411.         SetNewParms ();
  412.         // respawn        
  413.         PutClientInServer ();
  414.     }
  415.     else
  416.     {    // restart the entire server
  417.         localcmd ("restart\n");
  418.     }
  419. };
  420.  
  421.  
  422. /*
  423. ============
  424. ClientKill
  425.  
  426. Player entered the suicide command
  427. ============
  428. */
  429. void() ClientKill =
  430. {
  431.     if (self.suicide_count > 3) {
  432.         sprint(self, "You have suicided too much already.\n");
  433.         return;
  434.     }
  435.     bprint (self.netname);
  436.     bprint (" suicides\n");
  437.     DropRune();
  438.     TeamCaptureDropFlag();
  439.     set_suicide_frame ();
  440.     self.modelindex = modelindex_player;
  441.     self.frags = self.frags - 2;    // extra penalty
  442.     self.score = self.score - 2;
  443.     self.suicide_count = self.suicide_count + 1;
  444.     respawn ();
  445. };
  446.  
  447. void() SilentKill =
  448. {
  449.     set_suicide_frame ();
  450.     self.modelindex = modelindex_player;
  451.     respawn ();
  452. };
  453.  
  454. float(vector v) CheckSpawnPoint =
  455. {
  456.     return FALSE;
  457. };
  458.  
  459. /*
  460. ============
  461. SelectSpawnPoint
  462.  
  463. Returns the entity to spawn at
  464. ============
  465. */
  466. entity() SelectSpawnPoint =
  467. {
  468.     local    entity spot;
  469.     
  470. // testinfo_player_start is only found in regioned levels
  471.     spot = find (world, classname, "testplayerstart");
  472.     if (spot)
  473.         return spot;
  474.         
  475. // choose a info_player_deathmatch point
  476.     if (coop)
  477.     {
  478.         lastspawn = find(lastspawn, classname, "info_player_coop");
  479.         if (lastspawn == world)
  480.             lastspawn = find (lastspawn, classname, "info_player_start");
  481.         if (lastspawn != world)
  482.             return lastspawn;
  483.     }
  484.     else if (deathmatch)
  485.     {
  486.         if (!self.killed) {
  487.             spot = TeamCaptureSpawn();
  488.             if (spot != world) 
  489.                 return spot;
  490.         }
  491.         lastspawn = find(lastspawn, classname, "info_player_deathmatch");
  492.         if (lastspawn == world)
  493.             lastspawn = find (lastspawn, classname, "info_player_deathmatch");
  494.         if (lastspawn != world)
  495.             return lastspawn;
  496.     }
  497.  
  498.     if (serverflags)
  499.     {    // return with a rune to start
  500.         spot = find (world, classname, "info_player_start2");
  501.         if (spot)
  502.             return spot;
  503.     }
  504.     
  505.     spot = find (world, classname, "info_player_start");
  506.     if (!spot)
  507.         error ("PutClientInServer: no info_player_start on level");
  508.     
  509.     return spot;
  510. };
  511.  
  512. /*
  513. ===========
  514. PutClientInServer
  515.  
  516. called each time a player is spawned
  517. ============
  518. */
  519. void() DecodeLevelParms;
  520. void() PlayerDie;
  521.  
  522.  
  523. void() PutClientInServer =
  524. {
  525.     local    entity spot;
  526.  
  527.     spot = SelectSpawnPoint ();
  528. //ZOID: Minimize chance of telefragging someone, from Johannes Plass
  529. //(plass@dipmza.physik.uni-mainz.de) ServerModules package
  530.     spot = TelefragSelectSpawnPoint(spot);
  531.  
  532.     self.classname = "player";
  533.     self.health = 100;
  534.     self.curse_time = 0;
  535.     self.stone_time = 0;
  536.     self.had_tbolt = 0;
  537.     self.regen_rocket = 0;
  538.     self.balder_time = 0;
  539.     self.balder_slowdown = 0;
  540.     self.takedamage = DAMAGE_AIM;
  541.     self.solid = SOLID_SLIDEBOX;
  542.     self.movetype = MOVETYPE_WALK;
  543.     self.show_hostile = 0;
  544.     self.loki_possessed=0;
  545.     self.lock_velocity='0 0 0';
  546.     self.grenade_time = 2.5;
  547.     self.max_health = 100;
  548.     self.flags = FL_CLIENT;
  549.     self.air_finished = time + 12;
  550.     self.dmg = 2;           // initial water damage
  551.     self.super_damage_finished = 0;
  552.     self.super_sound = 0;
  553.     self.holy=0;    
  554.     self.radsuit_finished = 0;
  555.     self.invisible_finished = 0;
  556.     self.invincible_finished = 0;
  557.     self.effects = 0;
  558.     self.invincible_time = 0;
  559.     self.staydeadtime = 0;
  560.     self.rune_notice_time = 0;
  561.     self.rune_num = 0;
  562.     self.msg_center = 0;
  563.     self.touch = SUB_Null;
  564.  
  565.     msg_entity=self;
  566.     WriteByte(MSG_ONE, 5);
  567.     WriteEntity(MSG_ONE, self);
  568.  
  569.     DecodeLevelParms ();
  570.     
  571.     W_SetCurrentAmmo ();
  572.  
  573.     self.attack_finished = time;
  574.     self.th_pain = player_pain;
  575.     self.th_die = PlayerDie;
  576.     
  577.     self.deadflag = DEAD_NO;
  578. // paustime is set by teleporters to keep the player from moving a while
  579.     self.pausetime = 0;
  580.     
  581. //    spot = SelectSpawnPoint ();
  582.  
  583.     self.origin = spot.origin + '0 0 1';
  584.     self.angles = spot.angles;
  585.     self.fixangle = TRUE;        // turn this way immediately
  586.  
  587. // oh, this is a hack!
  588.     setmodel (self, "progs/eyes.mdl");
  589.     modelindex_eyes = self.modelindex;
  590.  
  591.     setmodel (self, "progs/player.mdl");
  592.  
  593.     modelindex_player = self.modelindex;
  594.  
  595.     setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
  596.     
  597.     self.view_ofs = '0 0 22';
  598.  
  599.     player_stand1 ();
  600.     
  601.     if (deathmatch || coop)
  602.     {
  603.         makevectors(self.angles);
  604.         spawn_tfog (self.origin + v_forward*20);
  605.     }
  606.  
  607.     spawn_tdeath (self.origin, self);
  608. };
  609.  
  610.  
  611. /*
  612. =============================================================================
  613.  
  614.                 QUAKED FUNCTIONS
  615.  
  616. =============================================================================
  617. */
  618.  
  619.  
  620. /*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24)
  621. The normal starting point for a level.
  622. */
  623. void() info_player_start =
  624. {
  625. };
  626.  
  627.  
  628. /*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24)
  629. Only used on start map for the return point from an episode.
  630. */
  631. void() info_player_start2 =
  632. {
  633. };
  634.  
  635.  
  636. void() SpawnRunes;
  637.  
  638. /*
  639. saved out by quaked in region mode
  640. */
  641. void() testplayerstart =
  642. {
  643. };
  644.  
  645. /*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24)
  646. potential spawning position for deathmatch games
  647. */
  648. void() info_player_deathmatch =
  649. {
  650.     local entity ghost_daemon;
  651.     local entity rspawn;
  652.  
  653.     ghost_daemon=spawn();
  654.     ghost_daemon.think=ghost_daemon_think;
  655.     ghost_daemon.nextthink=time+1;
  656.     if (deathmatch) {
  657.         // spawn the runes
  658.         rspawn = spawn();
  659.         rspawn.nextthink = time + 0.1;
  660.         rspawn.think = SpawnRunes;
  661.     }
  662. };
  663.  
  664. void() info_player_team1 =
  665. {
  666. };
  667.  
  668. void() info_player_team2 =
  669. {
  670. };
  671.  
  672. /*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24)
  673. potential spawning position for coop games
  674. */
  675. void() info_player_coop =
  676. {
  677. };
  678.  
  679. /*
  680. ===============================================================================
  681.  
  682. RULES
  683.  
  684. ===============================================================================
  685. */
  686.  
  687. /*
  688. go to the next level for deathmatch
  689. only called if a time or frag limit has expired
  690. */
  691. void() NextLevel =
  692. {
  693.     local entity o;
  694.  
  695.     if (mapname == "start")
  696.     {
  697.         if (!cvar("registered"))
  698.         {
  699.             mapname = "e1m1";
  700.         }
  701.         else if (!(serverflags & 1))
  702.         {
  703.             mapname = "e1m1";
  704.             serverflags = serverflags | 1;
  705.         }
  706.         else if (!(serverflags & 2))
  707.         {
  708.             mapname = "e2m1";
  709.             serverflags = serverflags | 2;
  710.         }
  711.         else if (!(serverflags & 4))
  712.         {
  713.             mapname = "e3m1";
  714.             serverflags = serverflags | 4;
  715.         }
  716.         else if (!(serverflags & 8))
  717.         {
  718.             mapname = "e4m1";
  719.             serverflags = serverflags - 7;
  720.         }
  721.  
  722.         o = spawn();
  723.         o.map = mapname;
  724.     }
  725.     else
  726.     {
  727. //ZOID: RandomLevel is called.  Note that RandomLevel handles Capture
  728. //levels as well.
  729.         o = spawn();
  730.         o.map = RandomLevel(mapname);
  731.  
  732.         // find a trigger changelevel
  733. //        o = find(world, classname, "trigger_changelevel");
  734.  
  735.         // go back to start if no trigger_changelevel
  736. //        if (!o)
  737. //        {
  738. //            mapname = "start";
  739. //            o = spawn();
  740. //            o.map = mapname;
  741. //        }
  742.     }
  743.  
  744.     nextmap = o.map;
  745.     gameover = TRUE;
  746.     
  747.     if (o.nextthink < time)
  748.     {
  749.         
  750. //        p = find (world, classname, "player");
  751. //        while (p!=world)
  752. //        {
  753. //            f=random();
  754. //            if (p!=self) {
  755. //                if (f<0.5)
  756. //                    p.team=TEAM_COLOR1 + 1;
  757. //                else
  758. //                    p.team=TEAM_COLOR2 + 1;
  759. //            }
  760. //        p=find(p, classname, "player");
  761. //        }
  762.  
  763.         o.think = execute_changelevel;
  764.         o.nextthink = time + 0.1;
  765.     }
  766. };
  767.  
  768. // Return a new random level, that doesn't match old
  769.  
  770. // Rewriten for CTF
  771. // uses the server temp1 cvar for level tracking
  772. // temp1 is mapped out as:
  773. //  bit 16 to 12 for id level num 0xf800, 63488
  774. //  bit 11 to 7 for Custom level num 0x0f80, 3968
  775. //  bit 6 to 0 for percent of custom CTF levels 0x007f, 127
  776. // server ops should just set temp1 to the percent and the start id/ctf
  777. // levels will be zero (first level)
  778. // 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536
  779. // ---------------- --------------------- ---------------------------
  780. // x x x x  x  x  x
  781. //                  x   x   x   x    x
  782. //                                        x    x    x     x     x
  783. //
  784. string(string old) RandomLevel =
  785. {
  786.         if (teamplay & TEAM_CAPTURE_FLAG) {
  787.                 // capture levels
  788.                 if (old == "e1m1") return "e1m2";
  789.         if (old == "e1m2") return "e1m3";
  790.                 if (old == "e1m3") return "e1m4";
  791.                 if (old == "e1m4") return "e1m6";
  792.                 if (old == "e1m6") return "ctf2m1";
  793.             if (old == "ctf2m1") return "ctf2m2";
  794.             if (old == "ctf2m2") return "ctf2m3";
  795.             if (old == "ctf2m3") return "ctf2m4";
  796.             if (old == "ctf2m4") return "ctf2m5";
  797.             if (old == "ctf2m5") return "ctf2m6";
  798.              if (old == "ctf2m6") return "ctf2m7";
  799.             if (old == "ctf2m7") return "ctf2m8";
  800.         if (old == "ctf2m8") return "e2m1";
  801.         if (old == "e2m1") return "e2m2";
  802.                 if (old == "e2m2") return "e2m3";
  803.                 if (old == "e2m3") return "e2m5";
  804.                 if (old == "e2m5") return "e4m3";
  805.                 if (old == "e4m3") return "e4m5";
  806.                 if (old == "e4m5") return "e4m6";
  807.                 if (old == "e4m6") return "dm3";
  808.                 if (old == "dm3") return "dm6";
  809.                 return "e1m1";
  810.         }
  811.  
  812. };
  813.  
  814. /*
  815. ============
  816. CheckRules
  817.  
  818. Exit deathmatch games upon conditions
  819. ============
  820. */
  821. void() CheckRules =
  822. {
  823.     local    float        timelimit;
  824.     local    float        fraglimit;
  825.         local   float           total1, total2;
  826.     local     entity         p, mvp1, mvp2;
  827.     local     float        mvp1_score, mvp2_score;    
  828.     
  829.     if (gameover)    // someone else quit the game already
  830.         return;
  831.         
  832.     timelimit = cvar("timelimit") * 60;
  833.     fraglimit = cvar("fraglimit");
  834.     
  835.     if ((timelimit && time >= timelimit) || (fraglimit && self.frags >= fraglimit))
  836.     {
  837.                 total1 = total2 = 0;
  838.         mvp1_score=mvp2_score=0;
  839.                 p = find(world, classname, "player");
  840.                 while (p != world) {
  841.                         if (p.lastteam == TEAM_COLOR1 + 1)
  842.             {
  843.                 if (teamplay&TEAM_CAPTURE_UNIF)
  844.                 {
  845.                     if (p.frags>total1)
  846.                         total1=p.frags;
  847.                     if (p.score>mvp1_score)
  848.                     {
  849.                         mvp1_score=p.score;
  850.                         mvp1=p;
  851.                     }
  852.                 }
  853.                 else
  854.                     total1 = total1 + p.frags;
  855.             }                
  856.                         else if (p.lastteam == TEAM_COLOR2 + 1)
  857.             {
  858.                 if (teamplay&TEAM_CAPTURE_UNIF)
  859.                 {
  860.                     if (p.frags>total2)
  861.                         total2=p.frags;
  862.                     if (p.score>mvp2_score)
  863.                     {
  864.                         mvp2=p;
  865.                         mvp2_score=p.score;
  866.                     }
  867.                 }
  868.                 else
  869.                     total2 = total2 + p.frags;
  870.             }            
  871.                         p = find(p, classname, "player");
  872.                 }
  873.         if (teamplay&TEAM_CAPTURE_UNIF)
  874.         {
  875.             bprint("Red team M.V.P.: ");
  876.             bprint(mvp1.netname);
  877.             bprint("\nBlue team M.V.P.: ");
  878.             bprint(mvp2.netname);
  879.             bprint("\n");
  880.         }
  881.  
  882.         NextLevel ();
  883.         return;
  884.     }
  885. };
  886.  
  887. //============================================================================
  888.  
  889. void() PlayerDeathThink =
  890. {
  891.     local entity    old_self;
  892.     local float        forward;
  893.  
  894.     if ((self.flags & FL_ONGROUND))
  895.     {
  896.         forward = vlen (self.velocity);
  897.         forward = forward - 20;
  898.         if (forward <= 0)
  899.             self.velocity = '0 0 0';
  900.         else    
  901.             self.velocity = forward * normalize(self.velocity);
  902.     }
  903.  
  904. // wait for all buttons released
  905.     if (self.deadflag == DEAD_DEAD)
  906.     {
  907.         if (self.button2 || self.button1 || self.button0)
  908.             return;
  909.         self.deadflag = DEAD_RESPAWNABLE;
  910.         return;
  911.     }
  912.  
  913. // wait for any button down
  914.     if (!self.button2 && !self.button1 && !self.button0)
  915.         return;
  916.  
  917.     self.button0 = 0;
  918.     self.button1 = 0;
  919.     self.button2 = 0;
  920.     respawn();
  921. };
  922.  
  923.  
  924. void() PlayerJump =
  925. {
  926.     local vector start, end;
  927.  
  928.     if (self.flags & FL_WATERJUMP)
  929.         return;
  930.     
  931.     if (self.waterlevel >= 2)
  932.     {
  933.         if (self.rune_num == ITEM_RUNE_HERMES)
  934.         {
  935.             if (self.watertype == CONTENT_WATER)
  936.                 self.velocity_z = 300;
  937.             else if (self.watertype == CONTENT_SLIME)
  938.                 self.velocity_z = 100;
  939.             else
  940.                 self.velocity_z = 80;
  941.         }
  942.         else
  943.         {
  944.             if (self.watertype == CONTENT_WATER)
  945.                 self.velocity_z = 150;
  946.             else if (self.watertype == CONTENT_SLIME)
  947.                 self.velocity_z = 80;
  948.             else
  949.             {
  950.                 if (self.rune_num == ITEM_RUNE_VULCAN)
  951.                     self.velocity_z = 150;
  952.                 else
  953.                     self.velocity_z = 50;
  954.             }
  955.         }
  956.  
  957.         if ((self.swim_flag < time) &&
  958.             (self.rune_num != ITEM_RUNE_HERMES))
  959.         {
  960.             self.swim_flag = time + 1;
  961.             if (random() < 0.5)
  962.                 playsound (self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM);
  963.             else
  964.                 playsound (self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM);
  965.         }
  966.  
  967.         return;
  968.     }
  969.  
  970.     if (!(self.flags & FL_ONGROUND))
  971.         return;
  972.  
  973.     if (!(self.flags & FL_JUMPRELEASED))
  974.         return;        // don't pogo stick
  975.  
  976.     self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
  977.  
  978.     self.flags = self.flags - FL_ONGROUND;    // don't stairwalk
  979.     
  980.     self.button2 = 0;
  981. // player jumping sound
  982.     playsound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
  983.     if (self.rune_num == ITEM_RUNE_WEREWOLF)
  984.     {
  985.         self.velocity_z = self.velocity_z + 600;
  986.         self.velocity_x = self.velocity_x * 2.0;
  987.         self.velocity_y = self.velocity_y * 2.0;
  988.     }
  989.     else
  990.         self.velocity_z = self.velocity_z + 270;
  991. };
  992.  
  993.  
  994. /*
  995. ===========
  996. WaterMove
  997.  
  998. ============
  999. */
  1000. .float    dmgtime;
  1001.  
  1002. void() WaterMove =
  1003. {
  1004.     if (self.movetype == MOVETYPE_NOCLIP)
  1005.         return;
  1006.     if (self.health < 0)
  1007.         return;
  1008.  
  1009.     if (self.waterlevel != 3)
  1010.     {
  1011.         if (!((self.rune_num==ITEM_RUNE_VULCAN) &&
  1012.             (self.watertype==CONTENT_LAVA)))
  1013.         {
  1014.             if ((self.air_finished < time) && (self.air_finished!=0)) {
  1015.                 playsound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
  1016.             }
  1017.             else if (self.air_finished < time + 9) {
  1018.                 playsound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
  1019.             }
  1020.     
  1021.             self.air_finished = time + 12;
  1022.             self.dmg = 2;
  1023.         }
  1024.     }
  1025.  
  1026.     else if ((self.air_finished < time) &&
  1027.             (self.rune_num != ITEM_RUNE_POSEIDON))
  1028.     {    // drown!
  1029.         if (self.pain_finished < time)
  1030.         {
  1031.             self.dmg = self.dmg + 2;
  1032.             if (self.dmg > 15)
  1033.                 self.dmg = 10;
  1034.             T_Damage (self, world, world, self.dmg);
  1035.             self.pain_finished = time + 1;
  1036.         }
  1037.     }
  1038.     
  1039.     if (!self.waterlevel)
  1040.     {
  1041.         if (self.flags & FL_INWATER)
  1042.         {    
  1043.             // play leave water sound
  1044.             playsound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
  1045.             self.flags = self.flags - FL_INWATER;
  1046.  
  1047.         }
  1048.         return;
  1049.     }
  1050.  
  1051.     if ((self.watertype == CONTENT_LAVA) &&
  1052.         (self.rune_num == ITEM_RUNE_ALIBABA))
  1053.     {
  1054.         KiziTeleportToBase();
  1055.         clientmsg(self, "You've escaped yet another tight\nsituation, Alibaba.\n");
  1056.     }
  1057.  
  1058.     if (((self.watertype != CONTENT_LAVA) || (self.waterlevel==0)) &&
  1059.         ((self.rune_num == ITEM_RUNE_VULCAN) ||
  1060.         (self.rune_num == ITEM_RUNE_IFRITE)))
  1061.         self.rune_time = -1;
  1062.     
  1063.     if ((self.watertype == CONTENT_LAVA) && (self.rune_num !=  ITEM_RUNE_GOLOM))
  1064.     {    // do damage
  1065.         if (self.dmgtime < time)
  1066.         {
  1067.             if ((self.rune_num != ITEM_RUNE_VULCAN) &&
  1068.                 (self.rune_num != ITEM_RUNE_IFRITE)) {
  1069.                 playsound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
  1070.                 if (self.radsuit_finished > time)
  1071.                     self.dmgtime = time + 1;
  1072.                 else
  1073.                     self.dmgtime = time + 0.2;
  1074.                 T_Damage (self, world, world, 10*self.waterlevel);
  1075.             } else
  1076.             if (self.rune_time == -1)
  1077.                 self.rune_time = time + 0.25;
  1078.         
  1079.         }
  1080.     }
  1081.     else if ((self.watertype == CONTENT_SLIME) &&
  1082.         (self.rune_num != ITEM_RUNE_GOLOM))
  1083.     {    // do damage
  1084.         if (self.dmgtime < time && self.radsuit_finished < time)
  1085.         {
  1086.             self.dmgtime = time + 1;
  1087.             T_Damage (self, world, world, 4*self.waterlevel);
  1088.         }
  1089.     }
  1090.     
  1091.     if ( !(self.flags & FL_INWATER) )
  1092.     {    
  1093.  
  1094. // player enter water sound
  1095.  
  1096.         if ((self.watertype == CONTENT_LAVA) && (self.rune_num != ITEM_RUNE_GOLOM))
  1097.             playsound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
  1098.         if ((self.watertype == CONTENT_WATER) && (self.rune_num != ITEM_RUNE_GOLOM))
  1099.             playsound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
  1100.         if ((self.watertype == CONTENT_SLIME) && (self.rune_num != ITEM_RUNE_GOLOM))
  1101.             playsound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
  1102.  
  1103.         self.flags = self.flags + FL_INWATER;
  1104.         self.dmgtime = 0;
  1105.     }
  1106.     
  1107.     if (!(self.flags & FL_WATERJUMP) && (self.rune_num != ITEM_RUNE_HERMES) && (self.rune_num != ITEM_RUNE_POSEIDON)) 
  1108.         self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
  1109.     if ((!self.flags&FL_WATERJUMP) && (self.rune_num == ITEM_RUNE_HERMES)
  1110.         && ((self.last_flight_watertype == CONTENT_WATER) ||
  1111.             (self.last_flight_watertype == CONTENT_SLIME) ||
  1112.             (self.last_flight_watertype == CONTENT_LAVA)))
  1113.         self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
  1114. };
  1115.  
  1116. void() CheckWaterJump =
  1117. {
  1118.     local vector start, end;
  1119.  
  1120. // check for a jump-out-of-water
  1121.     makevectors (self.angles);
  1122.     start = self.origin;
  1123.     start_z = start_z + 8; 
  1124.     v_forward_z = 0;
  1125.     normalize(v_forward);
  1126.     end = start + v_forward*24;
  1127.     traceline (start, end, TRUE, self);
  1128.     if (trace_fraction < 1)
  1129.     {    // solid at waist
  1130.         start_z = start_z + self.maxs_z - 8;
  1131.         end = start + v_forward*24;
  1132.         self.movedir = trace_plane_normal * -50;
  1133.         traceline (start, end, TRUE, self);
  1134.         if (trace_fraction == 1)
  1135.         {    // open at eye level
  1136.             self.flags = self.flags | FL_WATERJUMP;
  1137.             self.velocity_z = 225;
  1138.             self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
  1139.             self.teleport_time = time + 2;    // safety net
  1140.             return;
  1141.         }
  1142.     }
  1143.  
  1144. };
  1145.  
  1146.  
  1147. /*
  1148. ================
  1149. PlayerPreThink
  1150.  
  1151. Called every frame before physics are run
  1152. ================
  1153. */
  1154. void() PlayerPreThink=
  1155. {
  1156.     local    float    mspeed, aspeed;
  1157.     local    float    r,q;
  1158.     local entity p, oself,oldself;
  1159.     local entity kam, e;
  1160.     local string s;
  1161.     local vector v, src, dir;
  1162.  
  1163.  
  1164.     // SUCK: This is part of the ghost detection code.
  1165.     self.last_thought=time;
  1166.  
  1167.     if ((teamplay&TEAM_FORWARD_PLAYERS) &&
  1168.         ((self.shuffle==1) && (self.netname!="unconnected")))
  1169.     {
  1170.         sprint(self, "\n\nThis server is full.\n");
  1171.         sprint(self, "Forwarding you to finite.mit.edu...\n\n");
  1172.         stuffcmd(self, "connect 18.238.0.138\n");
  1173.     }
  1174.  
  1175.     if (self.regchecktime < time)
  1176.     {
  1177.         checkreg();
  1178.         self.regchecktime = time + 0.5;
  1179.     }
  1180.  
  1181.  
  1182.     if (self.inc_thought_count<time)
  1183.     {
  1184.         self.thought_count=self.thought_count + 1;
  1185.         self.inc_thought_count=time + 0.1;
  1186.     }
  1187.     
  1188.     if (intermission_running)
  1189.     {
  1190.         IntermissionThink ();    // otherwise a button could be missed between
  1191.         return;                    // the think tics
  1192.     }
  1193.     if (self.staydeadtime && self.staydeadtime > time)
  1194.         return;// wait a bit before respawn
  1195.  
  1196. // *TEAMPLAY*
  1197.     if (coop && TEAM_STRICT_COOP)
  1198.         return;
  1199.  
  1200.     if (self.view_ofs == '0 0 0')
  1201.         return;        // intermission or finale
  1202.  
  1203.     makevectors (self.v_angle);
  1204.  
  1205.     if (self.motd_time && self.motd_time < time)
  1206.         MOTD();
  1207.  
  1208.  
  1209.     if ((self.status_time < time) || (self.msg_pending))
  1210.     {
  1211.         if (self.displaying_rune_info == 1)
  1212.         {
  1213.             self.msg_center = 1;
  1214.             SetRuneInfoMsg();
  1215.         }
  1216.  
  1217.         if ((self.status_time == -1) && (self.msg_pending==1) &&
  1218.             (self.motd_time==0))
  1219.         {
  1220.             self.msg_center = 1;
  1221.             printstatus();
  1222.         }
  1223.         else if ((self.status_time != -1) && (!self.motd_time))
  1224.             printstatus();
  1225.         if (self.status_time != -1)
  1226.             self.status_time = time+1.5;
  1227.     }
  1228.  
  1229.     CheckRules ();
  1230.  
  1231.     if (self.rune_num == ITEM_RUNE_HERMES)
  1232.     {
  1233.         v=self.origin+'0 0 1';
  1234.         self.watertype=pointcontents(v);
  1235.         if ((self.watertype == CONTENT_WATER) ||
  1236.         (self.watertype == CONTENT_SLIME) ||
  1237.         (self.watertype == CONTENT_LAVA))
  1238.         {
  1239.             self.waterlevel=3;
  1240.             if (self.last_flight_watertype != self.watertype)
  1241.                 self.air_finished=time+12;
  1242.         }
  1243.         else
  1244.             self.waterlevel=0;
  1245.  
  1246.         if (self.last_flight_watertype==self.watertype)
  1247.             self.flags=self.flags|FL_INWATER;
  1248.         else
  1249.             self.flags=self.flags - (self.flags&FL_INWATER);
  1250.         self.last_flight_watertype=self.watertype;
  1251.     }
  1252.     WaterMove ();
  1253.     if (self.rune_num == ITEM_RUNE_HERMES)
  1254.     {
  1255.         self.watertype=CONTENT_EMPTY;
  1256.         self.waterlevel=3;
  1257.         self.flags=self.flags|FL_INWATER;
  1258.         if ((self.last_flight_watertype != CONTENT_WATER) &&
  1259.             (self.last_flight_watertype != CONTENT_SLIME) &&
  1260.             (self.last_flight_watertype != CONTENT_LAVA))
  1261.             self.velocity = 1.4*self.velocity;
  1262.         self.air_finished = time + 100;
  1263.     }
  1264.  
  1265.     if (self.rune_num == ITEM_RUNE_VULCAN)
  1266.         self.velocity = 0.90*self.velocity;
  1267.  
  1268.     if (self.rune_num == ITEM_RUNE_YTR)
  1269.     {
  1270.         q=v_forward_x*self.velocity_x + v_forward_y*self.velocity_y +
  1271.         v_forward_z*self.velocity_z;
  1272.         r=vlen(self.velocity);
  1273.         if (r == 0) q=1;
  1274.         else q=q/(r*r);
  1275.         v=self.velocity*q;
  1276.         self.velocity = self.velocity + v*100;
  1277.     }
  1278.  
  1279.  
  1280.  
  1281. // *TEAMPLAY*
  1282. // TeamCheckLock performs all necessary teamlock checking, and performs all
  1283. // actions needed.
  1284.     TeamCheckLock();
  1285.  
  1286.     if (self.waterlevel == 2)
  1287.         CheckWaterJump ();
  1288.  
  1289.     if (self.deadflag >= DEAD_DEAD)
  1290.     {
  1291.         PlayerDeathThink ();
  1292.         return;
  1293.     }
  1294.     
  1295.     if (self.deadflag == DEAD_DYING)
  1296.         return;    // dying, so do nothing
  1297.  
  1298.     if (self.button2)
  1299.     {
  1300.         PlayerJump ();
  1301.     }
  1302.     else
  1303.         self.flags = self.flags | FL_JUMPRELEASED;
  1304.  
  1305.  
  1306. // teleporters can force a non-moving pause time    
  1307.     if (time < self.pausetime)
  1308.         self.velocity = '0 0 0';
  1309.  
  1310.         oself=self;
  1311.         if (teamplay&TEAM_CAPTURE_UNIF) {
  1312.             p = find(p, classname, "player");
  1313.             while (p != world) {
  1314.                 self=p;
  1315.                 self.killed = 0;
  1316.                 if ((self.team == oself.team) &&
  1317.                 (self.lastteam == oself.lastteam) &&    
  1318.                 (self.frags > oself.frags))
  1319.                     oself.frags = self.frags;
  1320.     
  1321.                 p = find(p, classname, "player");
  1322.             }
  1323.         }
  1324.         self=oself;
  1325.  
  1326.     if ((self.curse_time != 0) && (self.curse_time > time))
  1327.     {
  1328.         if ((self.curse_time - time) > 4)
  1329.             W_Attack();
  1330.         PlayerJump();
  1331.     }
  1332.  
  1333.     if ((self.curse_time < time) && (self.curse_time != 0))
  1334.         self.curse_time = 0;
  1335.  
  1336.     if ((self.stone_time < time) && (self.stone_time != 0))
  1337.     {
  1338.         self.msg_center= 1;
  1339.         self.status_time = time;
  1340.         clientmsg(self, "The effects of Golom's stone touch\nhave worn off.\n");
  1341.         self.stone_time = 0;
  1342.     }
  1343.  
  1344.     if ((self.stone_time != 0) && (self.stone_time > time))
  1345.         self.velocity = '0 0 0';
  1346.  
  1347.     if (self.balder_time < time)
  1348.         self.balder_slowdown = 0;
  1349.  
  1350.     if ((self.rune_num == ITEM_RUNE_LOKI) &&
  1351.     (self.loki_possessed==1))
  1352.     {
  1353.         v=self.origin-self.loki_possession.origin;
  1354.         r=vlen(v);
  1355.         if (r>200)
  1356.         {        
  1357.             msg_entity=self;
  1358.             WriteByte(MSG_ONE, 143);
  1359.             WriteByte(MSG_ONE, 16);
  1360.             WriteEntity(MSG_ONE, self.loki_possession);
  1361.             WriteCoord(MSG_ONE, self.loki_possession.origin_x);
  1362.             WriteCoord(MSG_ONE, self.loki_possession.origin_y);
  1363.             WriteCoord(MSG_ONE, self.loki_possession.origin_z);
  1364.             e=findradius(self.loki_possession.origin, 600);
  1365.             while (e!=world)
  1366.             {
  1367.                 if (e!=self)
  1368.                 {
  1369.                     traceline(self.loki_possession.origin,
  1370.                     e.origin, FALSE, self.loki_possession);
  1371.                     if (trace_ent == e)
  1372.                     {
  1373. //                        WriteByte(MSG_ONE, 143);
  1374.                         WriteByte(MSG_ONE, 207);
  1375.                         WriteByte(MSG_ONE, 16);
  1376.                         WriteEntity(MSG_ONE, e);
  1377.                         WriteByte(MSG_ONE, e.frame);
  1378.                         WriteCoord(MSG_ONE, e.origin_x);
  1379.                         WriteCoord(MSG_ONE, e.origin_y);
  1380.                         WriteCoord(MSG_ONE, e.origin_z);
  1381.                     }
  1382.                 }
  1383.                 e=e.chain;
  1384.             }
  1385.         }
  1386.     }
  1387.  
  1388.     // SUCK: Check for all runes which require periodic execution
  1389.     if ((self.rune_time < time) && (self.rune_time != -1))
  1390.     {
  1391.         if (self.rune_num == ITEM_RUNE_SANDSTORM)
  1392.         {
  1393.             e=findradius(self.origin, 150);
  1394.             while (e)
  1395.             {
  1396.                 if ((e.team != self.team) && (e.classname == "player"))
  1397.                 {
  1398.                     stuffcmd(e, "bf\n");
  1399.                     e.deathweapon = "sandstorm";
  1400.                     T_Damage (e, self, self, 10);
  1401.                     e.deathweapon = "";
  1402.                     clientmsg(e, "You are caught in the sandstorm!\n");
  1403.                 }
  1404.                 e=e.chain;
  1405.             }
  1406.             self.rune_time = time + 0.5;
  1407.         }
  1408.         else if (self.rune_num == ITEM_RUNE_LOKI)
  1409.         {
  1410.             r=vlen(self.origin - self.last_origin);
  1411.             if ((r<30) && (self.loki_invis == 0))
  1412.             {
  1413.                 setmodel(self, string_null);
  1414.                 self.loki_invis=1;    
  1415.             }
  1416.             else if (((r>=30) || (self.loki_forcevis == 1))  &&
  1417.                 (self.loki_invis == 1))
  1418.             {
  1419.                 self.loki_invis=0;
  1420.                 self.loki_forcevis=0;
  1421.                 setmodel(self, "progs/player.mdl");
  1422.                 self.modelindex=modelindex_player;
  1423.             }
  1424.  
  1425.             self.last_origin=self.origin;
  1426.             self.rune_time=time+0.2;
  1427.         }
  1428.         else if (self.rune_num == ITEM_RUNE_ANKH)
  1429.         {
  1430.             if (self.health < 100)
  1431.             {
  1432.                 self.health = self.health + 2;
  1433.                 if (self.health > 100) self.health = 100;
  1434.             }
  1435.             self.rune_time = time + 1;
  1436.         }
  1437.         else if (self.rune_num == ITEM_RUNE_WEREWOLF)
  1438.         {
  1439.             if ((self.items & IT_ARMOR1)!=0)
  1440.                 self.items = self.items - IT_ARMOR1;
  1441.             if ((self.items & IT_ARMOR3)!=0)
  1442.                 self.items = self.items - IT_ARMOR3;
  1443.             self.items = self.items | IT_ARMOR2;
  1444.             self.armortype=0.6;
  1445.             self.armorvalue=100;
  1446.             if (self.health < 100)
  1447.             {
  1448.                 self.health = self.health + 4;
  1449.                 if (self.health > 100) self.health = 100;
  1450.             }
  1451.             self.rune_time = time + 0.5;
  1452.         }
  1453.         else if (self.rune_num == ITEM_RUNE_ALIBABA)
  1454.         {
  1455.             dir = aim(self, 10000);
  1456.             src = self.origin + v_forward*10;
  1457.             traceline(src, src + dir * 2048,
  1458.                 FALSE, self);
  1459.             src = 0.1*src + 0.9*trace_endpos;
  1460.             setorigin(self.bulb, src);    
  1461.         }
  1462.         else if (self.rune_num == ITEM_RUNE_ARTHUR)
  1463.         {
  1464.             e=findradius(self.origin, 600);
  1465.             while (e)
  1466.             {
  1467.                 if (e.team == self.team)
  1468.                 {
  1469.                     RegenerateAmmo(e);
  1470.                     if (e.health < 100)
  1471.                     {
  1472.                         e.health = e.health + 2;
  1473.                         if (e.health > 100)
  1474.                             e.health = 100;
  1475.                     }
  1476.                         
  1477.                 }
  1478.                 e=e.chain;
  1479.             }
  1480.             self.rune_time = time + 2;
  1481.         }
  1482.         else if (self.rune_num == ITEM_RUNE_WENDIGO)
  1483.         {
  1484.             self.health = self.health - 1;
  1485.             if (self.health <1)
  1486.                 Killed(self, self);
  1487.             self.rune_time = time + 1;
  1488.         }
  1489.         else if ((self.rune_num == ITEM_RUNE_WOLVERINE) &&
  1490.             (self.health < 100))
  1491.         {
  1492.             // Convert ammo to health.
  1493.             if (self.health < 100 && self.health>80)
  1494.             {
  1495.                 if (self.ammo_shells > 20)
  1496.                 {
  1497.                     self.ammo_shells=self.ammo_shells - 10;
  1498.                     self.health=self.health+2;
  1499.                 }
  1500.                 else if (self.ammo_nails > 50)
  1501.                 {
  1502.                     self.ammo_nails = self.ammo_nails - 4;
  1503.                     self.health=self.health+2;
  1504.                 }
  1505.             }
  1506.             else if (self.health < 81 && self.health > 50)
  1507.             {
  1508.                 if (self.ammo_shells > 10)
  1509.                 {
  1510.                     self.ammo_shells=self.ammo_shells - 10;
  1511.                     self.health=self.health+2;
  1512.                 }
  1513.                 if (self.ammo_nails > 10)
  1514.                 {
  1515.                     self.ammo_nails = self.ammo_nails - 6;
  1516.                     self.health=self.health+8;
  1517.                 }
  1518.             }
  1519.             else if (self.health < 50)
  1520.             {
  1521.                 if (self.ammo_shells > 10)
  1522.                 {
  1523.                     self.ammo_shells = self.ammo_shells - 10;
  1524.                     self.health = self.health + 5;
  1525.                 }
  1526.                 if (self.ammo_nails > 5)
  1527.                 {
  1528.                     self.ammo_nails = self.ammo_nails - 5;
  1529.                     self.health = self.health + 9;
  1530.                 }
  1531.                 if (self.ammo_rockets > 0)
  1532.                 {
  1533.                     self.ammo_rockets = self.ammo_rockets - 1;
  1534.                     self.health = self.health + 10;
  1535.                 }
  1536.                 if (self.ammo_cells > 5)
  1537.                 {
  1538.                     self.ammo_cells=self.ammo_cells - 5;
  1539.                     self.health = self.health + 15;
  1540.                 }
  1541.             }
  1542.             if (self.health >150)
  1543.                 self.health = 150;
  1544.             self.rune_time = self.rune_time + 0.5;
  1545.         }
  1546.         else if (self.rune_num == ITEM_RUNE_SAMURAI)
  1547.         {
  1548.             self.items = self.items | IT_ARMOR3;
  1549.             self.armorvalue = 200;
  1550.             self.armortype=0.8;
  1551.             self.rune_time = time + 25;
  1552.         }
  1553.         else if (self.rune_num == ITEM_RUNE_VIKING)
  1554.         {
  1555.             // Pillage power
  1556.             e = findradius(self.origin, 400);
  1557.             while (e)
  1558.             {
  1559.                 if ((e.flags & FL_ITEM) &&
  1560.                 (e.classname != "item_flag_team1") &&
  1561.                 (e.classname != "item_flag_team2") &&
  1562.                 (e.items!=IT_QUAD) &&
  1563.                 (e.items!=IT_INVISIBILITY) &&
  1564.                 (e.items!=IT_SUIT))
  1565.                 {
  1566.                     oself=self;
  1567.                     other=self;
  1568.                     self=e;
  1569.                     e.touch();
  1570.                     self=oself;
  1571.                 }
  1572.                 e=e.chain;
  1573.             }
  1574.             self.rune_time = self.rune_time + 0.5;
  1575.         }
  1576.         else if (self.rune_num == ITEM_RUNE_POSEIDON)
  1577.         {
  1578.             if ((self.trident_time < time) && (self.trident_time != 0))
  1579.             {
  1580.                 self.ammo_cells = 0;
  1581.                 if (self.weapon == IT_LIGHTNING)
  1582.                     self.currentammo = self.ammo_cells;
  1583.                 self.trident_time = 0;
  1584.             }
  1585.             if (self.ammo_cells < 100)
  1586.             {
  1587.                 self.ammo_cells = self.ammo_cells + 4;
  1588.                 if (self.weapon == IT_LIGHTNING)
  1589.                     self.currentammo=self.ammo_cells;
  1590.                 if (self.ammo_cells >= 100)
  1591.                 {
  1592.                     self.msg_center = 1;
  1593.                     clientmsg(self, "Your trident is charged, Poseidon.\n");
  1594.                     self.ammo_cells = 100;
  1595.                 }
  1596.             }
  1597.     
  1598.             // SUCK: Cause an earthquake.
  1599.             e=findradius(self.origin, 400);
  1600.             while (e!=world)
  1601.             {
  1602.                 if ((e.classname == "player") &&
  1603.                 (e.team != self.team))
  1604.                 {
  1605.                     e.velocity_x=e.velocity_x+random()*300;
  1606.                     e.velocity_y=e.velocity_y+random()*300;
  1607.                     e.velocity_z=e.velocity_z+random()*300;
  1608.                 }
  1609.                 e=e.chain;
  1610.             }
  1611.             if ((self.health < 100) && (pointcontents(self.origin) == CONTENT_WATER))
  1612.             {
  1613.                 self.health = self.health + 4;
  1614.                 if (self.health > 100)
  1615.                     self.health = 100;
  1616.             }    
  1617.             self.rune_time = time + 2;
  1618.         }
  1619.         else if (self.rune_num == ITEM_RUNE_VAMPIRE)
  1620.         {
  1621.             self.health = self.health - 2;
  1622.             if (self.health<40)
  1623.             {
  1624.                 self.msg_center=1;
  1625.                 clientmsg(self, "The bloodlust is upon you, vampire.\n");
  1626.             }
  1627.             self.rune_time = time + 1;
  1628.             if (self.health <1)
  1629.             {
  1630.                 self.deathweapon="vampire";
  1631.                 Killed(self, self);
  1632.                 self.deathweapon="";
  1633.             }
  1634.         }        
  1635.         else if (self.rune_num == ITEM_RUNE_PRIEST)
  1636.         {
  1637.             if (self.health < 100)
  1638.             {
  1639.                 self.health = self.health + 2;
  1640.                 if (self.health > 100)
  1641.                     self.health = 100;
  1642.             }
  1643.             self.rune_time = time + 0.5;
  1644.         }
  1645.         else if (self.rune_num == ITEM_RUNE_REGEN)
  1646.         {
  1647.             if (self.health<100)
  1648.                       {
  1649.                           self.health = self.health + 5;
  1650.                           if (self.health>100)
  1651.                         self.health=100;
  1652.                     RegenerationSound();
  1653.             }
  1654.             if (self.items&(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3))
  1655.             {
  1656.                 self.armorvalue = self.armorvalue + 5;
  1657.                         if ((self.items&IT_ARMOR3) && (self.armorvalue>200))
  1658.                                 self.armorvalue=200;
  1659.                 else if ((self.items&IT_ARMOR2) && (self.armorvalue>150))
  1660.                                 self.armorvalue=150;
  1661.                             else if ((self.items&IT_ARMOR1) && (self.armorvalue>100))
  1662.                                 self.armorvalue=100;
  1663.                 else
  1664.                     RegenerationSound();
  1665.                         if (self.armorvalue>250) self.armorvalue=200;
  1666.                    }
  1667.                     self.rune_time = time + 0.5;
  1668.         }
  1669.         else if (self.rune_num == ITEM_RUNE_VULCAN)
  1670.         {
  1671.             if (self.armorvalue < 250)
  1672.                 self.armorvalue = self.armorvalue + 1;
  1673.             self.rune_time = time + 0.25;
  1674.             if (self.waterlevel == 0)
  1675.                 self.rune_time = -1;
  1676.         }
  1677.         else if (self.rune_num == ITEM_RUNE_IFRITE)
  1678.         {
  1679.             if (self.health < 100)
  1680.             {
  1681.                 self.health = self.health + 10;
  1682.                 if (self.health > 100)
  1683.                     self.health = 100;
  1684.             }
  1685.             self.rune_time = time + 0.5;
  1686.             if (self.waterlevel == 0)
  1687.                 self.rune_time = -1;
  1688.         }
  1689.         else 
  1690.             self.rune_time = -1;
  1691.     }
  1692.  
  1693.     if(time > self.attack_finished && self.currentammo == 0 && 
  1694.         self.weapon != IT_AXE && self.weapon != IT_HOOK)
  1695.     {
  1696.         self.weapon = W_BestWeapon ();
  1697.         W_SetCurrentAmmo ();
  1698.     }
  1699.     if (self.lock_velocity!='0 0 0')
  1700.         self.velocity=self.lock_velocity;
  1701.     if (self.lock_time < time)
  1702.         self.lock_velocity='0 0 0';
  1703. };
  1704.     
  1705. /*
  1706. ================
  1707. CheckPowerups
  1708.  
  1709. Check for turning off powerups
  1710. ================
  1711. */
  1712. void() CheckPowerups =
  1713. {
  1714.     if (self.health <= 0)
  1715.         return;
  1716.  
  1717. // invisibility
  1718.     if (self.invisible_finished)
  1719.     {
  1720. // sound and screen flash when items starts to run out
  1721.         if (self.invisible_sound < time) {
  1722.             playsound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
  1723.             self.invisible_sound = time + ((random() * 3) + 1);
  1724.         }
  1725.  
  1726.  
  1727.         if (self.invisible_finished < time + 3)
  1728.         {
  1729.             if (self.invisible_time == 1)
  1730.             {
  1731.                 sprint (self, "Ring of Shadows magic is fading\n");
  1732.                 stuffcmd (self, "bf\n");
  1733.                 playsound (self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM);
  1734.                 self.invisible_time = time + 1;
  1735.             }
  1736.             
  1737.             if (self.invisible_time < time)
  1738.             {
  1739.                 self.invisible_time = time + 1;
  1740.                 stuffcmd (self, "bf\n");
  1741.             }
  1742.         }
  1743.  
  1744.         if (self.invisible_finished < time)
  1745.         {    // just stopped
  1746.             self.items = self.items - (self.items&IT_INVISIBILITY);
  1747.             self.invisible_finished = 0;
  1748.             self.invisible_time = 0;
  1749.         }
  1750.         
  1751.     // use the eyes
  1752.         self.frame = 0;
  1753.         self.modelindex = modelindex_eyes;
  1754.     }
  1755.     else
  1756.         self.modelindex = modelindex_player;    // don't use eyes
  1757.  
  1758. // invincibility
  1759.     if (self.invincible_finished)
  1760.     {
  1761. // sound and screen flash when items starts to run out
  1762.         if (self.invincible_finished < time + 3)
  1763.         {
  1764.             if (self.invincible_time == 1)
  1765.             {
  1766.                 sprint (self, "Protection is almost burned out\n");
  1767.                 stuffcmd (self, "bf\n");
  1768.                 playsound (self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM);
  1769.                 self.invincible_time = time + 1;
  1770.             }
  1771.             
  1772.             if (self.invincible_time < time)
  1773.             {
  1774.                 self.invincible_time = time + 1;
  1775.                 stuffcmd (self, "bf\n");
  1776.             }
  1777.         }
  1778.         
  1779.         if (self.invincible_finished < time)
  1780.         {    // just stopped
  1781.             self.items = self.items - (self.items&IT_INVULNERABILITY);
  1782.             self.invincible_time = 0;
  1783.             self.invincible_finished = 0;
  1784.         }
  1785. // ZOID, next line isn't needed, EF_DIMLIGHT is handled by
  1786. // client.qc:CheckDimLight
  1787. //        if (self.invincible_finished > time)
  1788. //            self.effects = self.effects | EF_DIMLIGHT;
  1789. //        else
  1790. //            self.effects = self.effects - (self.effects & EF_DIMLIGHT);
  1791.     }
  1792.  
  1793. // super damage
  1794.     if (self.super_damage_finished)
  1795.     {
  1796.  
  1797. // sound and screen flash when items starts to run out
  1798.  
  1799.         if (self.super_damage_finished < time + 3)
  1800.         {
  1801.             if (self.super_time == 1)
  1802.             {
  1803.                 sprint (self, "Quad Damage is wearing off\n");
  1804.                 stuffcmd (self, "bf\n");
  1805.                 playsound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
  1806.                 self.super_time = time + 1;
  1807.             }      
  1808.             
  1809.             if (self.super_time < time)
  1810.             {
  1811.                 self.super_time = time + 1;
  1812.                 stuffcmd (self, "bf\n");
  1813.             }
  1814.         }
  1815.  
  1816.         if (self.super_damage_finished < time)
  1817.         {    // just stopped
  1818.             self.items = self.items - (self.items&IT_QUAD);
  1819.             self.super_damage_finished = 0;
  1820.             self.super_time = 0;
  1821.         }
  1822. // ZOID, next line isn't needed, EF_DIMLIGHT is handled by
  1823. // client.qc:CheckDimLight
  1824. //        if (self.super_damage_finished > time)
  1825. //            self.effects = self.effects | EF_DIMLIGHT;
  1826. //        else
  1827. //            self.effects = self.effects - (self.effects & EF_DIMLIGHT);
  1828.     }    
  1829.  
  1830. // suit    
  1831.     if (self.radsuit_finished)
  1832.     {
  1833.         self.air_finished = time + 12;        // don't drown
  1834.  
  1835. // sound and screen flash when items starts to run out
  1836.         if (self.radsuit_finished < time + 3)
  1837.         {
  1838.             if (self.rad_time == 1)
  1839.             {
  1840.                 sprint (self, "Air supply in Biosuit expiring\n");
  1841.                 stuffcmd (self, "bf\n");
  1842.                 playsound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
  1843.                 self.rad_time = time + 1;
  1844.             }
  1845.             
  1846.             if (self.rad_time < time)
  1847.             {
  1848.                 self.rad_time = time + 1;
  1849.                 stuffcmd (self, "bf\n");
  1850.             }
  1851.         }
  1852.  
  1853.         if (self.radsuit_finished < time)
  1854.         {    // just stopped
  1855.             self.items = self.items - IT_SUIT;
  1856.             self.rad_time = 0;
  1857.             self.radsuit_finished = 0;
  1858.         }
  1859.     }    
  1860.  
  1861.     // Check to see about DIMLIGHT effects
  1862.     CheckDimLight();
  1863. };
  1864.  
  1865.  
  1866. /*
  1867. ================
  1868. PlayerPostThink
  1869.  
  1870. Called every frame after physics are run
  1871. ================
  1872. */
  1873. void() PlayerPostThink =
  1874. {
  1875.     local    float    mspeed, aspeed;
  1876.     local    float    r;
  1877.  
  1878.         local   string  num;
  1879.  
  1880.     if (self.view_ofs == '0 0 0')
  1881.         return;        // intermission or finale
  1882.     if (self.deadflag)
  1883.         return;
  1884.         
  1885. // do weapon stuff
  1886.  
  1887.     W_WeaponFrame ();
  1888.  
  1889. // check to see if player landed and play landing sound    
  1890.     if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) && (self.health > 0))
  1891.     {
  1892.         if (self.watertype == CONTENT_WATER)
  1893.             playsound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
  1894.         else if (self.jump_flag < -650)
  1895.         {
  1896.             T_Damage (self, world, world, 5); 
  1897.             playsound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
  1898.             self.deathtype = "falling";
  1899.         }
  1900.         else
  1901.             playsound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
  1902.  
  1903.         self.jump_flag = 0;
  1904.     }
  1905.  
  1906.     if (!(self.flags & FL_ONGROUND))
  1907.         self.jump_flag = self.velocity_z;
  1908.  
  1909.     CheckPowerups ();
  1910. };
  1911.  
  1912.  
  1913. /*
  1914. ===========
  1915. ClientConnect
  1916.  
  1917. called when a player connects to a server
  1918. ============
  1919. */
  1920. void() ClientConnect =
  1921. {
  1922.     local entity p, oself, e;
  1923.     local float n;
  1924.     local string s;
  1925.  
  1926.     if (teamplay&TEAM_FORWARD_PLAYERS)
  1927.     {
  1928.         n=0;
  1929.         p=find(world, classname, "player");
  1930.         while (p!=world)
  1931.         {
  1932.             if (p.thought_count > 0)
  1933.                 n=n+1;
  1934.             p=find(p, classname, "player");
  1935.         }
  1936.     
  1937.         if (n> (fwd_supported_players - 2))
  1938.             self.shuffle=1;
  1939.         else
  1940.             self.shuffle=0;
  1941.     }
  1942.         
  1943.     bprint (self.netname);
  1944.     bprint (" entered the game\n");
  1945.         
  1946.     LogMsg(self, "CONNECT");
  1947.  
  1948.     self.motd_time = time + 1;
  1949.     self.bottom_line=12;    
  1950.     self.motd_count = 0;
  1951.     self.status_time = -1;
  1952.     self.msg_pending=0;
  1953.     self.msg_center=0;
  1954.  
  1955.     self.displaying_rune_info = 0;
  1956.  
  1957.     self.regname = "";
  1958.     self.regcode = 0;
  1959.     self.regcodenum = 0;
  1960.     self.needsreg = 0;
  1961.     self.regstart = 0;
  1962.     self.regtries = 0;
  1963.     self.regchecktime = time + 15;
  1964.  
  1965.     self.suicide_count = 0;
  1966.     self.num_deaths = 0;
  1967.     self.num_kills = 0;
  1968.     self.score = 0;
  1969.     self.killed = 0;
  1970.     playsound (self, CHAN_BODY, "wizard/wsight.wav", 1, ATTN_NONE);
  1971. // *TEAMPLAY*
  1972.      // If this is our first connection, parm10 is < 0
  1973.      // Set lastteam negative.
  1974.      if(parm10 < 0 && teamplay > 0) {
  1975.          self.lastteam = -50;
  1976.         TeamCheckLock();
  1977.  
  1978.         if(teamplay & TEAM_LOCK_COLORS) // force a stuff cmd in think
  1979.             self.player_flag = self.player_flag | TEAM_STUFF_COLOR;
  1980.         if ((teamplay & TEAM_CAPTURE_CUSTOM) && (teamplay & TEAM_CAPTURE_FLAG)) {
  1981.             if (self.lastteam == TEAM_COLOR1 + 1)
  1982.                 self.skin = 1;
  1983.             else
  1984.                 self.skin = 3;
  1985.             if (random() < 0.5)
  1986.                 self.skin = self.skin + 1; // visor dude
  1987.             self.player_flag = self.player_flag - (self.player_flag & 65280);
  1988.             self.player_flag = self.player_flag | (self.skin * 256);  
  1989.         }
  1990.     }
  1991.  
  1992. // a client connecting during an intermission can cause problems
  1993.     if (intermission_running)
  1994.         ExitIntermission ();
  1995. };
  1996.  
  1997.  
  1998. /*
  1999. ===========
  2000. ClientDisconnect
  2001.  
  2002. called when a player disconnects from a server
  2003. ============
  2004. */
  2005. void() ClientDisconnect =
  2006. {
  2007.     if (gameover)
  2008.         return;
  2009.     // if the level end trigger has been activated, just return
  2010.     // since they aren't *really* leaving
  2011.  
  2012.     // let everyone else know
  2013.     bprint (self.netname);
  2014.     bprint (" left the game with ");
  2015.     bprint (ftos(self.frags));
  2016.     bprint (" frags\n");
  2017.     playsound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
  2018.     DropRune();
  2019.     TeamCaptureDropFlag();
  2020.     set_suicide_frame ();
  2021.  
  2022.     self.displaying_rune_info = 0;
  2023.  
  2024.     self.regname = "";
  2025.     self.regcode = 0;
  2026.     self.regcodenum = 0;
  2027.     self.needsreg = 0;
  2028.     self.regstart = 0;
  2029.     self.regtries = 0;
  2030.     self.regchecktime = 0;
  2031.     self.thought_count=0;
  2032.  
  2033.     LogMsg(self, "DISCONNECT");
  2034. };
  2035.  
  2036. // *TEAMPLAY*
  2037. // Prototypes
  2038.  
  2039. float(entity targ, entity attacker) TeamFragPenalty;
  2040. void(entity targ, entity attacker) TeamDeathPenalty;
  2041.  
  2042. /*
  2043. ===========
  2044. ClientObituary
  2045.  
  2046. called when a player dies
  2047. ============
  2048. */
  2049. void(entity targ, entity attacker) ClientObituary =
  2050. {
  2051.     local    float rnum;
  2052.     local    string deathstring, deathstring2, what, s;
  2053.     local    entity p, oself;
  2054.     rnum = random();
  2055.  
  2056.     if (targ.classname == "player")
  2057.     {
  2058.         if (attacker.classname == "teledeath")
  2059.         {
  2060.             bprint (targ.netname);
  2061.             bprint (" was fist-fucked by ");
  2062.             bprint (attacker.owner.netname);
  2063.             bprint ("\n");
  2064.  
  2065.             if (attacker.team == targ.team) return;
  2066.             oself=self;
  2067.             if (teamplay&TEAM_CAPTURE_UNIF) {
  2068.                 p = find(p, classname, "player");
  2069.                 while (p != world) {
  2070.                     self=p;
  2071.                     self.killed = 0;
  2072.                     if (self.team == attacker.team) 
  2073.                         self.frags = self.frags + 1;
  2074.                     p = find(p, classname, "player");
  2075.                 }
  2076.             }
  2077.             self=oself;
  2078.             attacker.score=attacker.score+1;
  2079.             attacker.num_kills=attacker.num_kills+1;
  2080.             if (!(teamplay&TEAM_CAPTURE_UNIF))
  2081.                 attacker.frags = attacker.frags + 1;
  2082.  
  2083.             LogPlayerDMDeath(targ, attacker.owner, "telefrag");
  2084.             return;
  2085.         }
  2086.  
  2087.         if (attacker.classname == "teledeath2")
  2088.         {
  2089.             bprint ("Satan's power deflects ");
  2090.             bprint (targ.netname);
  2091.             bprint ("'s telefrag\n");
  2092.  
  2093.             targ.score=targ.score - 1;
  2094.             targ.frags = targ.frags - 1;
  2095.             LogPlayerDeath(targ, "telefrag");
  2096.             return;
  2097.         }
  2098.  
  2099.         if (attacker.classname == "player")
  2100.         {
  2101.             if (targ == attacker)
  2102.             {
  2103.                 // killed self
  2104.                 oself=self;
  2105.                 if (teamplay&TEAM_CAPTURE_UNIF) {
  2106.                     while (p != world) {
  2107.                         self=p;
  2108.                         self.killed = 0;
  2109.                         if (self.team == attacker.team) 
  2110.                             self.frags = self.frags - 1;
  2111.                         p = find(p, classname, "player");
  2112.                     }
  2113.                 }
  2114.                 self=oself;
  2115.                 attacker.score=attacker.score - 1;
  2116.                 if (!(teamplay&TEAM_CAPTURE_UNIF))
  2117.                     attacker.frags = attacker.frags - 1;
  2118.                 bprint (targ.netname);
  2119.                 
  2120.                 if (targ.weapon == 64 && targ.waterlevel > 1)
  2121.                 {
  2122.                     bprint (" discharges into the water.\n");
  2123.                     LogPlayerDeath(targ, "discharge");
  2124.                     return;
  2125.                 }
  2126.                 if (targ.weapon == IT_GRENADE_LAUNCHER) {
  2127.                     bprint (" discovers blast radius\n");
  2128.                     LogPlayerDeath(targ, "grenade");
  2129.                 } else if (targ.team != targ.lastteam) {
  2130.                     //ZOID: try if player was gibbed for changing teams
  2131.                     if (teamplay & TEAM_STATIC_TEAMS)
  2132.                         bprint (" tried to change teams\n");
  2133.                     else
  2134.                         bprint (" changed teams\n");
  2135.                     LogPlayerDeath(targ, "teamchange");
  2136.                 } else 
  2137.                 if (targ.deathweapon == "vampire")
  2138.                 {
  2139.                     bprint (" is overcome by bloodlust.\n");
  2140.                     LogPlayerDeath(targ, "rocket");
  2141.                 }
  2142.                 else
  2143.                 {
  2144.                     bprint (" discovers blast radius\n");
  2145.                     LogPlayerDeath(targ, "rocket");
  2146.                 }
  2147.                 return;
  2148.             }
  2149.             else if ( (teamplay == 2) && (targ.team > 0)&&(targ.team == attacker.team) )
  2150.             {
  2151.                 if (rnum < 0.25)
  2152.                     deathstring = " mows down a teammate\n";
  2153.                 else if (rnum < 0.50)
  2154.                     deathstring = " checks his glasses\n";
  2155.                 else if (rnum < 0.75)
  2156.                     deathstring = " gets a frag for the other team\n";
  2157.                 else
  2158.                     deathstring = " loses another friend\n";
  2159.                 bprint (attacker.netname);
  2160.                 bprint (deathstring);
  2161.                 attacker.frags = attacker.frags - 1;
  2162.                 attacker.score=attacker.score - 1;
  2163.                 return;
  2164.             }
  2165.             else
  2166.             {
  2167. // *TEAMPLAY*
  2168. // TeamFragPenalty returns true if the attacker gets a frag penalty for
  2169. // killing this target.  It also deducts frags as needed.
  2170.                 if (!TeamFragPenalty(targ, attacker))
  2171.                     //ZOID: If in capture mode, do we count regular frags?
  2172.                     if ((targ.player_flag & ITEM_ENEMY_FLAG) &&
  2173.                         targ.team != attacker.team) {
  2174.                     oself=self;
  2175.                     if (teamplay&TEAM_CAPTURE_UNIF) {
  2176.                         p = find(world, classname, "player");
  2177.                         while (p != world) {
  2178.                             self=p;
  2179.                             self.killed = 0;
  2180.                             if (self.team == attacker.team) 
  2181.                                 self.frags = self.frags + TEAM_UNIFORM_CARRIER_BONUS;
  2182.                             p = find(p, classname, "player");
  2183.                         }
  2184.                     }
  2185.                     self=oself;
  2186.                         attacker.num_kills = attacker.num_kills + 1;
  2187.                         attacker.score=attacker.score+TEAM_CAPTURE_FRAG_CARRIER_BONUS;
  2188.                         //ZOID: fragged enemy flag carrier
  2189.                         if (!(teamplay&TEAM_CAPTURE_UNIF)) 
  2190.                             attacker.frags = attacker.frags + TEAM_CAPTURE_FRAG_CARRIER_BONUS;
  2191.                         sprint(attacker, "Enemy carrier killed: ");
  2192.                         if (!(teamplay&TEAM_CAPTURE_UNIF))
  2193.                             s = ftos(TEAM_CAPTURE_FRAG_CARRIER_BONUS);
  2194.                         else
  2195.                             s = ftos(TEAM_UNIFORM_CARRIER_BONUS);
  2196.                         sprint(attacker, s);
  2197.                         sprint(attacker, " point bonus\n");
  2198.                     } else
  2199.                     {
  2200.                         oself=self;
  2201.                         if (teamplay&TEAM_CAPTURE_UNIF) {
  2202.                         p = find(world, classname, "player");
  2203.                             while (p != world) {
  2204.                                 self=p;
  2205.                                 self.killed = 0;
  2206.                                 if (self.team == attacker.team) 
  2207.                                     self.frags = self.frags + 1;
  2208.                                 p = find(p, classname, "player");
  2209.                             }
  2210.                         }
  2211.                         self=oself;
  2212.                         attacker.score=attacker.score+1;
  2213.                         attacker.num_kills=attacker.num_kills+1;
  2214.                         if (!(teamplay&TEAM_CAPTURE_UNIF))
  2215.                             attacker.frags = attacker.frags + 1;
  2216.                     }
  2217.   
  2218. // *TEAMPLAY*
  2219. // TeamDeathPenalty kills the attacker if necessary and adjusts frags to
  2220. // offset the one frag penalty for dying.
  2221.                 TeamDeathPenalty(targ, attacker);
  2222.                 rnum = attacker.weapon;
  2223.                 if (targ.deathweapon == "shylock")
  2224.                 {
  2225.                     deathstring = " had a pound of flesh removed by ";
  2226.                     deathstring2 = "\n";
  2227.                     what="shylock";
  2228.                 }
  2229.                 else if (targ.deathweapon == "sandstorm")
  2230.                 {
  2231.                     deathstring = " was buried by ";
  2232.                     deathstring2 = "'s sandstorm\n";
  2233.                     what="sandstorm";
  2234.                 }
  2235.                 else if (targ.deathweapon == "werewolf")
  2236.                 {
  2237.                     deathstring = " was mauled by ";
  2238.                     deathstring2 = "\n";
  2239.                     what="werewolf";
  2240.                 }
  2241.                 else if (targ.deathweapon == "holywater")
  2242.                 {
  2243.                     deathstring = " was exorcised by ";
  2244.                     deathstring2 = "'s holy water.\n";
  2245.                     what="holywater";
  2246.                 }
  2247.                 else
  2248.                 if (rnum == IT_AXE)
  2249.                 {
  2250.                     if (attacker.rune_num == ITEM_RUNE_VAMPIRE)
  2251.                         deathstring = " feels ";
  2252.                     deathstring = " was ax-murdered by ";
  2253.                     if (attacker.rune_num == ITEM_RUNE_VAMPIRE)
  2254.                     {
  2255.                         deathstring = " was drained by ";
  2256.                         deathstring2 = "'s vampire bite\n";
  2257.                     }
  2258.                     what = "axe";
  2259.                 }
  2260.                 else
  2261.                 if (rnum == IT_HOOK) {
  2262.                     if (random() < 0.5)
  2263.                         deathstring = " was disembowled by ";
  2264.                     else
  2265.                         deathstring = " was hooked by ";
  2266.                     deathstring2 = "\n";
  2267.                     what = "hook";
  2268.                 }
  2269.                 else
  2270.                 if (rnum == IT_SHOTGUN)
  2271.                 {
  2272.                     deathstring = " chewed on ";
  2273.                     deathstring2 = "'s boomstick\n";
  2274.                     what = "shotgun";
  2275.                 }
  2276.                 else
  2277.                 if (rnum == IT_SUPER_SHOTGUN)
  2278.                 {
  2279.                     deathstring = " ate 2 loads of ";
  2280.                     deathstring2 = "'s buckshot\n";
  2281.                     what = "supershotgun";
  2282.                 }
  2283.                 else
  2284.                 if (rnum == IT_NAILGUN)
  2285.                 {
  2286.                     deathstring = " was nailed by ";
  2287.                     deathstring2 = "'s my first nailgun\n";
  2288.                     what = "nailgun";
  2289.                 }
  2290.                 else
  2291.                 if (rnum == IT_SUPER_NAILGUN)
  2292.                 {
  2293.                     deathstring = " was perforated by ";
  2294.                     deathstring2 = "\n";
  2295.                     what = "supernailgun";
  2296.                 }
  2297.                 else
  2298.                 if (rnum == IT_GRENADE_LAUNCHER)
  2299.                 {
  2300.                     deathstring = " eats ";
  2301.                     deathstring2 = "'s dingus\n";
  2302.                     if (targ.health < -40)
  2303.                     {
  2304.                         deathstring = " was gibbed by ";
  2305.                         deathstring2 = "'s dingus\n";
  2306.                     }
  2307.                     what = "grenade";
  2308.                 }
  2309.                 else
  2310.                 if (rnum == IT_ROCKET_LAUNCHER)
  2311.                 {
  2312.                     deathstring = " rides ";
  2313.                     deathstring2 = "'s rocket\n";
  2314.                     if (targ.health < -40)
  2315.                     {
  2316.                         deathstring = " was gibbed by ";
  2317.                         deathstring2 = "'s rocket\n" ;
  2318.                     }
  2319.                     what = "rocket";
  2320.                 }
  2321.                 else
  2322.                 if (rnum == IT_LIGHTNING)
  2323.                 {
  2324.                     if (attacker.rune_num==ITEM_RUNE_THOR)
  2325.                     {
  2326.                         deathstring=" feels ";
  2327.                         deathstring2="'s Thor Power\n";
  2328.                         what = "lightning";
  2329.                     }
  2330.                     else if ((attacker.rune_num == ITEM_RUNE_POSEIDON) && (attacker.ammo_cells > 89)) {
  2331.                         deathstring = " is pierced by ";
  2332.                         deathstring2 = "'s trident\n";
  2333.                         what = "lightning";
  2334.                     }
  2335.                     else { if (attacker.waterlevel > 1)
  2336.                         deathstring = " accepts ";
  2337.                     else
  2338.                         deathstring = " is ";
  2339.                     if ((attacker.waterlevel > 1) && (attacker.rune_num != ITEM_RUNE_HERMES) && (attacker.rune_num != ITEM_RUNE_POSEIDON))
  2340.                         deathstring2 = "'s discharge\n";
  2341.                     else
  2342.                         deathstring2 = "'s whore\n";
  2343.                     what = "lightning";
  2344.                     }
  2345.                 }
  2346.                 bprint (targ.netname);
  2347.                 bprint (deathstring);
  2348.                 bprint (attacker.netname);
  2349.                 bprint (deathstring2);
  2350.                 LogPlayerDMDeath(targ, attacker, what);
  2351.             }
  2352.             return;
  2353.         }
  2354.         else
  2355.         {
  2356.  
  2357.             
  2358.             oself=self;
  2359.             if (teamplay&TEAM_CAPTURE_UNIF) {
  2360.                 p = find(p, classname, "player");
  2361.                 while (p != world) {
  2362.                     self=p;
  2363.                     self.killed = 0;
  2364.                     if (self.team == targ.team) 
  2365.                         self.frags = self.frags - 1;
  2366.                     p = find(p, classname, "player");
  2367.                 }
  2368.             }
  2369.             self=oself;
  2370.             targ.score=targ.score - 1;
  2371.             if (!(teamplay&TEAM_CAPTURE_UNIF))
  2372.                 targ.frags = targ.frags - 1;
  2373.             bprint (targ.netname);
  2374.  
  2375.             // tricks and traps
  2376.             if (attacker.classname == "explo_box")
  2377.             {
  2378.                 bprint (" blew up\n");
  2379.                 LogPlayerDeath(targ, "explosion");
  2380.                 return;
  2381.             }
  2382.             if (attacker.solid == SOLID_BSP && attacker != world)
  2383.             {    
  2384.                 bprint (" was squished\n");
  2385.                 LogPlayerDeath(targ, "squished");
  2386.                 return;
  2387.             }
  2388.             if (attacker.classname == "trap_shooter" || attacker.classname == "trap_spikeshooter")
  2389.             {
  2390.                 bprint (" was spiked\n");
  2391.                 LogPlayerDeath(targ, "spiked");
  2392.                 return;
  2393.             }
  2394.             if (attacker.classname == "fireball")
  2395.             {
  2396.                 bprint (" ate a lavaball\n");
  2397.                 LogPlayerDeath(targ, "fireball");
  2398.                 return;
  2399.             }
  2400.             if (attacker.classname == "trigger_changelevel")
  2401.             {
  2402.                 bprint (" tried to leave\n");
  2403.                 LogPlayerDeath(targ, "noexit");
  2404.                 return;
  2405.             }
  2406.  
  2407.             // in-water deaths
  2408.             rnum = targ.watertype;
  2409.             if (rnum == -3)
  2410.             {
  2411.                 if (random() < 0.5)
  2412.                     bprint (" sleeps with the fishes\n");
  2413.                 else
  2414.                     bprint (" sucks it down\n");
  2415.                 LogPlayerDeath(targ, "drowned");
  2416.                 return;
  2417.             }
  2418.             else if (rnum == -4)
  2419.             {
  2420.                 if (random() < 0.5)
  2421.                     bprint (" gulped a load of slime\n");
  2422.                 else
  2423.                     bprint (" can't exist on slime alone\n");
  2424.                 LogPlayerDeath(targ, "slimed");
  2425.                 return;
  2426.             }
  2427.             else if (rnum == -5)
  2428.             {
  2429.                 if (targ.health < -15)
  2430.                 {
  2431.                     bprint (" burst into flames\n");
  2432.                     LogPlayerDeath(targ, "melted");
  2433.                     return;
  2434.                 }
  2435.                 if (random() < 0.5)
  2436.                     bprint (" turned into hot slag\n");
  2437.                 else
  2438.                     bprint (" visits the Volcano God\n");
  2439.                 LogPlayerDeath(targ, "melted");
  2440.                 return;
  2441.             }
  2442.  
  2443.             // fell to their death?
  2444.             if (targ.deathtype == "falling")
  2445.             {
  2446.                 targ.deathtype = "";
  2447.                 bprint (" fell to his death\n");
  2448.                 LogPlayerDeath(targ, "falling");
  2449.                 return;
  2450.             }
  2451.  
  2452.             // Unknown cause of death.
  2453.             LogPlayerDeath(targ, "died");
  2454.             bprint (" died\n");
  2455.         }
  2456.     }
  2457. };
  2458.